package com.server;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.io.*;
import java.net.*;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author wwf
 * 容器启动入口
 * @date 2020年12月25日 10:27:31
 */
public class BootStarp {
    private int port=9090;//容器监听端口号
    private Mapper mapper = new Mapper();
    //容器初始化
    public  void init() throws DocumentException, ClassNotFoundException, InstantiationException, IllegalAccessException, FileNotFoundException {
        loadMAP();
        //loadServlet();
    }

    private void loadMAP() throws DocumentException, ClassNotFoundException, FileNotFoundException, InstantiationException, IllegalAccessException {
        InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream("server.xml");
        SAXReader saxReader = new SAXReader();
        Document document = saxReader.read(resourceAsStream);
        Element rootElement = document.getRootElement();
        List<Host> hosts=new ArrayList<Host>();
        List<Element> elements = rootElement.selectNodes("//Service");
        for (Element element : elements) {
            Element connectorElement = (Element) element.selectSingleNode("//Connector");
             port = Integer.parseInt(connectorElement.attributeValue("port"));
            List<Element> hostelements =  element.selectNodes("//Host");
            for (Element hostelement : hostelements) {
                String hostName = hostelement.attributeValue("name");
                String appBase = hostelement.attributeValue("appBase");
                Host host = new Host();
                host.setHostname(hostName+":"+port);

                List<AppContext> appContexts = getWrapServlets(appBase);
                //appContext.setWrapServlets(wrapServlets);
                //appContexts.add(appContext);
                host.setContext(appContexts);
                hosts.add(host);
                mapper.setHost(hosts);
            }


        }
    }

    private List<AppContext> getWrapServlets(String appBase) throws FileNotFoundException, DocumentException, IllegalAccessException, InstantiationException, ClassNotFoundException {
        List<AppContext> appContexts = new ArrayList<AppContext>();
        File file = new File(appBase);
        if(file.exists() && file.isDirectory()){
            File[] files = file.listFiles();
            for (File file1 : files) {
                if(file1.exists() && file1.isDirectory()){
                    AppContext appContext = new AppContext();
                    String appName = file1.getName();
                    appContext.setAppName(appName);
                    String appWebXmlPath = appBase+"\\"+appName+"\\WEB-INF\\web.xml";
                    String calssesPath = appBase+"\\"+appName+"\\WEB-INF\\classes";
                    File file2 = new File(appWebXmlPath);
                    FileInputStream fileInputStream = new FileInputStream(file2);
                    List<WrapServlet> wrapServlets = doParseWebxml(fileInputStream,calssesPath);
                    appContext.setWrapServlets(wrapServlets);
                    appContexts.add(appContext);
                }
            }
        }
        return appContexts;
    }

    /**
     *
     * @param
     * @param calssesPath
     * @return 解析项目中的xml
     * @throws DocumentException
     * @throws ClassNotFoundException
     * @throws IllegalAccessException
     * @throws InstantiationException
     */
    List<WrapServlet> doParseWebxml(InputStream inputStream, String calssesPath) throws DocumentException, ClassNotFoundException, IllegalAccessException, InstantiationException {
        List<WrapServlet> wrapServlets = new ArrayList<WrapServlet>();
        SAXReader saxReader = new SAXReader();
        Document document = saxReader.read(inputStream);
        Element rootElement = document.getRootElement();
        List<Element> elements = rootElement.selectNodes("//servlet");
        Iterator var6 = elements.iterator();

        while(var6.hasNext()) {
            Element element = (Element)var6.next();
            Element servletNameElement = (Element)element.selectSingleNode("//servlet-name");
            String servletname = servletNameElement.getTextTrim();
            Element servletClassElement = (Element)element.selectSingleNode("//servlet-class");
            String servletClass = servletClassElement.getTextTrim();
            Element servletmapping = (Element)rootElement.selectSingleNode("/web-app/servlet-mapping[servlet-name='" + servletname + "']");
            Element urlPartenElement = (Element)servletmapping.selectSingleNode("//url-pattern");
            String urlPaten = urlPartenElement.getTextTrim();
            WrapServlet wrapServlet = new WrapServlet();
            wrapServlet.setUrl(urlPaten);
           // String classFilePath = calssesPath+"\\"+servletClass.replaceAll("\\.","\\\\")+".class";
            try {
                URLClassLoader urlClassLoader = URLClassLoader.newInstance(new URL[] {
                        new URL(
                                "file:///"+calssesPath+"//"
                        )
                });
                Class clazz = urlClassLoader.loadClass(servletClass);
                //MyClassLoader myClassLoader = new MyClassLoader();
                wrapServlet.setServlet((HttpServlet)clazz.newInstance());
                wrapServlets.add(wrapServlet);
            } catch (MalformedURLException e) {
                e.printStackTrace();
            }

            //this.servlerMapping.put(urlPaten, (HttpServlet)Class.forName(servletClass).newInstance());
        }
        return wrapServlets;
    }

    private Map<String,HttpServlet> servlerMapping = new HashMap<String,HttpServlet>();

    private void loadServlet() throws DocumentException, ClassNotFoundException, IllegalAccessException, InstantiationException {
        InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream("web.xml");
        SAXReader saxReader = new SAXReader();
        Document document = saxReader.read(resourceAsStream);
        Element rootElement = document.getRootElement();
        List<Element> elements = rootElement.selectNodes("//servlet");
        Iterator var6 = elements.iterator();

        while(var6.hasNext()) {
            Element element = (Element)var6.next();
            Element servletNameElement = (Element)element.selectSingleNode("//servlet-name");
            String servletname = servletNameElement.getTextTrim();
            Element servletClassElement = (Element)element.selectSingleNode("//servlet-class");
            String servletClass = servletClassElement.getTextTrim();
            Element servletmapping = (Element)rootElement.selectSingleNode("/web-app/servlet-mapping[servlet-name='" + servletname + "']");
            Element urlPartenElement = (Element)servletmapping.selectSingleNode("//url-pattern");
            String urlPaten = urlPartenElement.getTextTrim();
            this.servlerMapping.put(urlPaten, (HttpServlet)Class.forName(servletClass).newInstance());
        }

    }


    //容器启动
    public void start() throws IOException {
        ServerSocket serverSocket = new ServerSocket(port);
        System.out.println("=====>>> Mycat started on port :"+port);
        while (true){
            Socket accept = serverSocket.accept();
            ExecutorService service = Executors.newFixedThreadPool(10);
            service.execute(new RequestProcessor(accept,this.mapper));
            //new Thread(new RequestProcessor(accept,servlerMapping)).start();
        }

    }
    public static void main(String[] args) throws IOException, DocumentException, ClassNotFoundException, IllegalAccessException, InstantiationException {
        //启动web容器
        BootStarp bootStarp = new BootStarp();
        bootStarp.init();
        bootStarp.start();
    }
}
